查看原文
其他

大吉大利,今晚吃凤梨 —— pinia 迁移随记

Jim Bytebase 2022-12-19

pinia 相比 vuex 我觉得最大的提升有下面 3 个:

  1. 概念更简单

  2. 对 TypeScript 的支持更好

  3. 对 composition API 的支持更好


下面就分别举一个简单的例子来说明下。



概念更简单


pinia 里没有 mutation 的概念了,如果你要 mutate state,那就直接对它赋值;如果你的赋值有比较复杂的逻辑,那就把它包成一个 Action——对,Action 概念统一了,并且也没有所谓 dispatch 和 commit 的概念了。


换言之,不管做什么 mutate,如果是同步的,我们就把 Action 定义成普通的函数,如果是异步的,我们就把 Action 定义成 async function,这也算是所见即所得了。


与此同时,namespace 的概念也没有了,所有的 module 都是一个独立的 store 模块,也不需要一个注册到根模块上这一类的动作,完全可以独立工作。而在 App 入口初的 createPinia 和 app.use(pinia) 更多来说是注册一个 provider 一类的东西,并没有真正注册各个 module。


正因为如此,pinia 的文档里也似乎有意在弱化 module 这个概念,比如它推荐的目录结构不再把所有的子模块都塞进一个叫 modules 的目录里面,而是一字长蛇阵平铺开来,像下面这样


因为在 vuex 里,modules 的注册是自顶而下的,index module 需要收集所有的 sub modules 然后再一次性 createStore。而 pinia 的 modules 其实没有集中注册的概念,所以可以定义得如此松散。


不过目前我们还是保留了 modules 目录,主要是为了稍微好看一点 ……



对 TypeScript 支持更好


因为没有了 commit 和 dispatch,也没有了 namespace,原本用字符串做 ID 的恶心事情都没了,而是

  • getters -> 直接访问字段

  • dispatch -> 直接调用成员方法

  • commit -> 当作 action 一样处理,直接调用成员方法


调用端这样去用,它的类型信息自然就友好多了



可以近似理解为,useXXStore() 得到的就是一个 XXStore 的 Singleton。它是一个具有 reactivity 的对象,并且身上附加了一些 getter 和成员方法。


不过在实现层面,算是有一些遗憾。目前 pinia 的类型声明极度依赖于 defineStore 的类型体操(类似于 vue 的 defineComponent),而如此复杂的推导也是有代价的。如果你偶尔写了“半个函数”,导致 defineStore 类型推导无法收敛,那么整个 store 的类型都会挂掉,只会得到满屏幕的红线,并且鼠标移上去也无法获得任何有用的提示信息。



对 composition API 的支持更好


有多好呢?它的 API 就是为 composable 而设计的。useXXStore() 是一个开销非常小的调用,完全可以随取随用,而无需考虑集中 useXXStore 再共享或者传参带着走。因此我们也可以写出类似这样的代码


这样,调用 hasFeature 的地方就不需要再显式地 useSubscriptionStore(),使用者甚至可以认为 hasFeature 是一个 magic,而不用知道它背后的 SubscriptionStore 任何细节。


类似的我们也可以发挥 reactivity 的优势,比如这样


用的时候就可以把某个 FeatureType 映射为一个 Reactive Value,比如


也就是说,一切我们在用 composition API 开发中常用的组合逻辑和 pattern,对于 pinia store 来说都适用。


再比如,我们之前经常用的一种“三段式” pattern,转成 pinia 代码后可能是这样


而如果我们用 composable 的指导思想,可以把它提取成这样


调用端就可以简化成


虽然用 vuex 的 composition API 可以做到完全一样的事情,但是坦率而言,pinia 以 composition API 为出发点就让人很有这种冲动去做这样的重构 ……


如果够狠的话,完全可以一点都不暴露 useXXStore,而把所有的逻辑都 compose 成普通的函数和 Reactive Value,甚至可以把前端的 State Management 和后端的数据同步整个儿都封装,哪怕它里面都是 magic。当然,可以是可以,有没有必要则另说了……

为科技创业公司做了5年代码审核后,我学到了什么?
适用于 MySQL 的 Schema 审核策略
Bytebase 1.1.1 - 2022.6.9
Bytebase 支持 --pg 背后的故事


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存